package org.framework.core.orm.support;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.framework.core.orm.IMapper;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

@Repository
public class MapperImpl implements IMapper {
	
	@Autowired
    private SessionFactory sessionFactory;
	
	@Autowired
	private JdbcTemplate jdbcTemplate;

	/**
	 * entity execute methods
	 */
	public void save(Object paramObject) {
		
		sessionFactory.getCurrentSession().persist(paramObject);
	}
	
	public void save(Object... paramObjects) {
		Session session = sessionFactory.getCurrentSession();
		for (Object paramObject : paramObjects) {
			session.persist(paramObject);
		}
	}
	
	public void save(Collection<?> paramCollectionOfObject) {
		Session session = sessionFactory.getCurrentSession();
		for (Object paramObject : paramCollectionOfObject) {
			session.persist(paramObject);
		}
	}
	
	public void saveOrUpdate(Object paramObject) {
		Session session = sessionFactory.getCurrentSession();
		session.merge(paramObject);
	}
	
	public void saveOrUpdate(Object... paramObjects) {
		Session session = sessionFactory.getCurrentSession();
		for (Object paramObject : paramObjects) {
			session.merge(paramObject);
		}
	}
	
	public void saveOrUpdate(Collection<?> paramCollectionOfObject) {
		Session session = sessionFactory.getCurrentSession();
		for (Object paramObject : paramCollectionOfObject) {
			session.merge(paramObject);
		}
	}
	
	public void update(Object paramObject) {
		Session session = sessionFactory.getCurrentSession();
		session.merge(paramObject);
	}
	
	public void update(Object... paramObjects) {
		Session session = sessionFactory.getCurrentSession();
		for (Object paramObject : paramObjects) {
			session.merge(paramObject);
		}
	}
	
	public void update(Collection<?> paramCollectionOfObject) {
		Session session = sessionFactory.getCurrentSession();
		for (Object paramObject : paramCollectionOfObject) {
			session.merge(paramObject);
		}
	}
	
	public void remove(Object paramObject) {
		Session session = sessionFactory.getCurrentSession();
		session.delete(paramObject);
	}
	
	public void remove(Object... paramObjects) {
		Session session = sessionFactory.getCurrentSession();
		for (Object paramObject : paramObjects) {
			session.delete(paramObject);
		}
	}
	
	public void remove(Collection<?> paramCollectionOfObject) {
		Session session = sessionFactory.getCurrentSession();
		for (Object paramObject : paramCollectionOfObject) {
			session.delete(paramObject);
		}
	}
	
	/**
	 * query single methods
	 */
	public Object queryUnique(String paramString, Object[] paramArrayOfObject) {
		Session session = sessionFactory.getCurrentSession();
		SQLQuery sqlQuery = session.createSQLQuery(paramString);
		if(paramArrayOfObject != null) {
			for (int i = 0; i < paramArrayOfObject.length; i++) {
				sqlQuery.setString(i, String.valueOf(paramArrayOfObject[i]));
			}
		}
		Object obj = sqlQuery.uniqueResult();
		session.clear();
		return obj;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T get(Class<T> paramClass, Serializable paramSerializable) {
		Session session = sessionFactory.getCurrentSession();
		T t = (T) session.get(paramClass, paramSerializable);
		session.clear();
		return t;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T load(Class<T> paramClass, Serializable paramSerializable) {
		Session session = sessionFactory.getCurrentSession();
		T t = (T) session.load(paramClass, paramSerializable);
		session.clear();
		return t;
	}
	
	/**
	 * query limit List<?> methods
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> query(String paramString, Class<T> paramClass, Object[] paramArrayOfObject, Integer paramInt1, Integer paramInt2) {
		Session session = sessionFactory.getCurrentSession();
		SQLQuery sqlQuery = session.createSQLQuery(paramString);
		if(paramArrayOfObject != null) {
			for (int i = 0; i < paramArrayOfObject.length; i++) {
				sqlQuery.setString(i, String.valueOf(paramArrayOfObject[i]));
			}
		}
		
		sqlQuery.addEntity(paramClass);
		if(paramInt1 != null)
			sqlQuery.setFirstResult(paramInt1);
		if(paramInt2 != null)
			sqlQuery.setMaxResults(paramInt2);
		
		List<T> list = sqlQuery.list();
		session.clear();
		return list;
	}
	
	public <T> List<T> query(String paramString, RowMapper<T> rowMapper, Object[] paramArrayOfObject) {
		return jdbcTemplate.query(paramString, rowMapper, paramArrayOfObject);
	}
	
	@SuppressWarnings("unchecked")
	public List<Object[]> query(String paramString, Object[] paramArrayOfObject, Integer paramInt1, Integer paramInt2) {
		Session session = sessionFactory.getCurrentSession();
		SQLQuery sqlQuery = session.createSQLQuery(paramString);
		if(paramArrayOfObject != null) {
			for (int i = 0; i < paramArrayOfObject.length; i++) {
				sqlQuery.setString(i, String.valueOf(paramArrayOfObject[i]));
			}
		}
		
		if(paramInt1 != null)
			sqlQuery.setFirstResult(paramInt1);
		if(paramInt2 != null)
			sqlQuery.setMaxResults(paramInt2);
		
		List<Object[]> list = sqlQuery.list();
		session.clear();
		return list;
	}

	public List<Map<String, Object>> queryForList(String paramString, Object[] paramArrayOfObject) {
		return jdbcTemplate.queryForList(paramString, paramArrayOfObject);
	}
	
	/**
	 * query all List<?> methods
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> loadAll(Class<T> paramClass) {
		Session session = sessionFactory.getCurrentSession();
		List<T> list = session.createQuery(" from " + paramClass.getName()).list();
		session.clear();
		return list;
	}
	
	
	/**
	 * execute methods
	 */
	public int execute(String paramString, Object[] paramArrayOfObject) {
		return jdbcTemplate.update(paramString, paramArrayOfObject);
	}
	
	public int[] batchExecute(String paramString, Object[] paramArrayOfObject) {
		
		return jdbcTemplate.batchUpdate(new String[]{});// .update(paramString, paramArrayOfObject);
	}
	
	public int count(String paramString, Object[] paramObject) {
		return ((Number)queryUnique(paramString, paramObject)).intValue();
	}
	
	
	
	
	
	
	
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
}
